﻿using DevelopTool.Bll.DbBlls;
using DevelopTool.Common;
using DevelopTool.Forms.BaseForms;
using DevelopTool.Forms.CommonControls;
using DevelopTool.Forms.DbForms.ReferenceForms;
using DevelopTool.Forms.LodingForm;
using DevelopTool.Model;
using DevelopTool.Model.CommonModels;
using DevelopTool.Model.DbModels;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.AxHost;

namespace DevelopTool.Forms.DbForms.PackageForms
{
    /// <summary>
    /// Oracle包信息窗体
    /// </summary>
    public partial class OraclePackageForm : BaseUIPage
    {
        /// <summary>
        /// 需要固定的首行列名
        /// </summary>
        private string _fixedFirstRowColumnName = string.Empty;
        /// <summary>
        /// 需要固定的首行列名
        /// </summary>
        public string FixedFirstRowColumnName
        {
            get
            {
                return this._fixedFirstRowColumnName;
            }
            set
            {
                this._fixedFirstRowColumnName = value;
            }
        }

        /// <summary>
        /// 连接信息
        /// </summary>
        private DbInfo dbInfo;

        /// <summary>
        /// Oracle操作类
        /// </summary>
        private OracleDbBll oracleDbBll;

        /// <summary>
        /// 查询条件
        /// </summary>
        private string queryKeyword;

        /// <summary>
        /// 查询实例
        /// </summary>
        private string queryDataBase;

        /// <summary>
        /// 查询资源名
        /// </summary>
        private string queryInfoName;


        private DataTable dataTable;

        /// <summary>
        /// DataGridView列信息集合
        /// </summary>
        private List<DataGridColumn> dataGridColumns = new List<DataGridColumn>()
              {
                { new DataGridColumn("OBJECT_NAME"){ColumnText="包名",Width=0,ColumnType = ColumnType.DefaultFilter | ColumnType.RowMain}},
                { new DataGridColumn("PACKAGE_TEXT"){ColumnText="包Sql",Width=0,ColumnType = ColumnType.DefaultFilter | ColumnType.LongText,ShowFormProperty=new ShowFormProperty(){
                BaseNameColumn="OBJECT_NAME"
                } }},
                { new DataGridColumn("PACKAGE_TEXT_LINE"){ColumnText="包行数",Width=-1}},
                { new DataGridColumn("PACKAGEBODY_TEXT"){ColumnText="包体Sql",Width=0,ColumnType = ColumnType.DefaultFilter | ColumnType.LongText,ShowFormProperty=new ShowFormProperty(){
                BaseNameColumn="OBJECT_NAME"
                } }},
                { new DataGridColumn("PACKAGEBODY_TEXT_LINE"){ColumnText="包体行数",Width=-1}},
                { new DataGridColumn("REFCOUNT"){ColumnText="依赖数量",Width=-1,ColumnType=ColumnType.CanClick}},
                { new DataGridColumn("OWNER"){ColumnText="实例",Width=100}},
                { new DataGridColumn("AGGREGATE"){ColumnText="聚合函数",Width=-1}},
                { new DataGridColumn("PIPELINED"){ColumnText="流水线函数",Width=-1}}
              };


        public OraclePackageForm(DbInfo dbInfo)
        {
            InitializeComponent();

            this.dbInfo = dbInfo.CloneObj();
        }

        public OraclePackageForm(DbInfo dbInfo,string queryKeyword)
        {
            InitializeComponent();

            this.dbInfo = dbInfo.CloneObj();
            this.queryKeyword = queryKeyword;
        }

        public OraclePackageForm(DbInfo dbInfo,string queryDataBase,string queryInfoName)
        {
            InitializeComponent();

            this.dbInfo = dbInfo.CloneObj();
            this.queryDataBase = queryDataBase;
            this.queryInfoName = queryInfoName;
        }

        private void OracleFuncInfoForm_Load(object sender,EventArgs e)
        {
            this.Disposed += this.OraclePackageForm_Disposed;

            this.oracleDbBll = new OracleDbBll(dbInfo);

            this.dataDisplayControl.DbInfo = this.dbInfo;

            this.dataDisplayControl.BindContextMenuStrip(this.ContextMenuStripDgv);//绑定右键菜单

            InitDate();
        }



        private void InitDate()
        {

            LoadingHelper.ShowLoading("获取包数据",() =>
            {
                //查询指定数据库包信息
                dataTable = oracleDbBll.GetPackages(this.queryDataBase,this.queryInfoName);
            });

            this.dataDisplayControl.BindData(dataTable,this.dataGridColumns,"OBJECT_NAME ASC");

            this.backgroundWorkerPackage.RunWorkerAsync(dataTable);//启动后台任务，获取包sql脚本信息 

        }


        private void dataDisplayControl_DataGridViewCellClick(DataGridViewEventArgs dataGridViewEventArgs)
        {
            if(dataGridViewEventArgs.MouseButton == MouseButtons.Left)//判断点的是不是左键
            {
                if(dataGridViewEventArgs.Column.Name == "REFCOUNT" && string.IsNullOrEmpty(dataGridViewEventArgs.Cell.Value.ToString()))
                {
                    string objectName = dataGridViewEventArgs.Row.Cells["OBJECT_NAME"].Value.ToString();//取得对象名
                    string owner = dataGridViewEventArgs.Row.Cells["OWNER"].Value.ToString();//取得表所有者
                    string refCount = string.Empty;
                    LoadingHelper.ShowLoading($"获取{objectName}依赖关系数量",() =>
                    {
                        refCount = oracleDbBll.GetObjectRefCount("PACKAGE BODY",objectName,owner);
                    });

                    dataGridViewEventArgs.Cell.Value = refCount;
                }
            }
        }


        private void dataDisplayControl_DataReLoad(object sender,EventArgs e)
        {
            InitDate();
        }


        private void 查看依赖关系ToolStripMenuItem_Click(object sender,EventArgs e)
        {

            UITabControl parentTabControl = this.GetParentControl<UITabControl>();
            if(parentTabControl != null)
            {
                string owner = this.dataDisplayControl.SelectedRowDic["OWNER"];
                string name = this.dataDisplayControl.SelectedRowDic["OBJECT_NAME"];
                TabControlHelper.AddPageToTabControl(parentTabControl,new OracleReferenceForm(this.dbInfo,owner,name,"PACKAGE BODY"),$"{dbInfo.NodeName}-{name}依赖",true,$"{name}-OracleReferenceForm");
            }
        }

        private void 添加到分组ToolStripMenuItem_Click(object sender,EventArgs e)
        {
            string dataBase = this.dataDisplayControl.SelectedRowDic["OWNER"];
            string name = this.dataDisplayControl.SelectedRowDic["OBJECT_NAME"];

            DbSourceGroupHelper.AddSourceToGroup(dataBase,name,"TResPackage",this.dbInfo);
        }

        #region 后台任务

        #region 获取包sql脚本

        /// <summary>
        /// 后台任务-执行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void backgroundWorkerPackage_DoWork(object sender,System.ComponentModel.DoWorkEventArgs e)
        {
            if(!(e.Argument is DataTable dataTable) || dataTable.Rows.Count == 0) return;

            //显示进度条
            this.Invoke(new Action(() =>
            {
                this.dataDisplayControl.ProcessBar.Visible = true;
                this.dataDisplayControl.ProcessBar.Maximum = dataTable.Rows.Count;
            }));

            //并行循环遍历DataTable
            Parallel.ForEach(dataTable.AsEnumerable(),(dataRow,state) =>
            {
                if(this.backgroundWorkerPackage.CancellationPending)
                {
                    e.Cancel = true;
                    state.Break();
                    return;
                }

                string owner = dataRow["OWNER"].ToString();
                string object_name = dataRow["OBJECT_NAME"].ToString();
                SourceText sourceText = null;
                try
                {
                    sourceText = this.oracleDbBll.GetSourceText(owner,object_name,"PACKAGE");//获取对象脚本
                }
                catch(Exception ex)
                {
                    sourceText = new SourceText() { Owner = owner,Object_Name = object_name,Text = ex.Message,LineNum = 1 };
                }

                backgroundWorkerPackage.ReportProgress(0,new Tuple<DataTable,SourceText>(dataTable,sourceText));//报告状态，展示结果
            });
        }

        /// <summary>
        /// 后台任务-报告
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void backgroundWorkerPackage_ProgressChanged(object sender,System.ComponentModel.ProgressChangedEventArgs e)
        {
            Tuple<DataTable,SourceText> tuple = e.UserState as Tuple<DataTable,SourceText>;

            //填充脚本信息
            for(int i = 0 ; i < tuple.Item1.Rows.Count ; i++)
            {
                if(tuple.Item1.Rows[i]["OWNER"].ToString() == tuple.Item2.Owner && tuple.Item1.Rows[i]["OBJECT_NAME"].ToString() == tuple.Item2.Object_Name)
                {
                    tuple.Item1.Rows[i]["PACKAGE_TEXT"] = tuple.Item2.Text;
                    tuple.Item1.Rows[i]["PACKAGE_TEXT_LINE"] = tuple.Item2.LineNum;
                    break;
                }
            }
            this.dataDisplayControl.ProcessBar.Value++;
        }

        /// <summary>
        /// 后台任务-完成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void backgroundWorkerPackage_RunWorkerCompleted(object sender,System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            if(e.Cancelled) return;

            this.dataDisplayControl.ProcessBar.Value = 0;

            //获取完包sql脚本后，接着获取包体sql脚本
            this.backgroundWorkerPackage_Body.RunWorkerAsync(this.dataTable);//启动后台任务，获取包体sql脚本信息 

            if(string.IsNullOrEmpty(this.queryInfoName))
                UINotifierHelper.ShowNotifier("已加载完成所有包sql脚本",UINotifierType.OK,"Oracle包",timeout: 2000);

        }

        #endregion

        #region 获取包体sql脚本

        private void backgroundWorkerPackage_Body_DoWork(object sender,System.ComponentModel.DoWorkEventArgs e)
        {
            if(!(e.Argument is DataTable dataTable) || dataTable.Rows.Count == 0) return;

            //并行循环遍历DataTable
            Parallel.ForEach(dataTable.AsEnumerable(),(dataRow,state) =>
            {
                if(this.backgroundWorkerPackage_Body.CancellationPending)
                {
                    e.Cancel = true;
                    state.Break();
                    return;
                }

                string owner = dataRow["OWNER"].ToString();
                string object_name = dataRow["OBJECT_NAME"].ToString();
                SourceText sourceText = null;
                try
                {
                    sourceText = this.oracleDbBll.GetSourceText(owner,object_name,"PACKAGE BODY");//获取对象脚本
                }
                catch(Exception ex)
                {
                    sourceText = new SourceText() { Owner = owner,Object_Name = object_name,Text = ex.Message,LineNum = 1 };
                }

                backgroundWorkerPackage_Body.ReportProgress(0,new Tuple<DataTable,SourceText>(dataTable,sourceText));//报告状态，展示结果
            });
        }

        private void backgroundWorkerPackage_Body_ProgressChanged(object sender,System.ComponentModel.ProgressChangedEventArgs e)
        {
            Tuple<DataTable,SourceText> tuple = e.UserState as Tuple<DataTable,SourceText>;

            //填充脚本信息
            for(int i = 0 ; i < tuple.Item1.Rows.Count ; i++)
            {
                if(tuple.Item1.Rows[i]["OWNER"].ToString() == tuple.Item2.Owner && tuple.Item1.Rows[i]["OBJECT_NAME"].ToString() == tuple.Item2.Object_Name)
                {
                    tuple.Item1.Rows[i]["PACKAGEBODY_TEXT"] = tuple.Item2.Text;
                    tuple.Item1.Rows[i]["PACKAGEBODY_TEXT_LINE"] = tuple.Item2.LineNum;
                    break;
                }
            }
            this.dataDisplayControl.ProcessBar.Value++;
        }

        private void backgroundWorkerPackage_Body_RunWorkerCompleted(object sender,System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            if(e.Cancelled) return;

            if(string.IsNullOrEmpty(this.queryInfoName))
                UINotifierHelper.ShowNotifier("已加载完成所有包体sql脚本",UINotifierType.OK,"Oracle包",timeout: 2000);

            this.dataDisplayControl.ProcessBar.Value = 0;
            this.dataDisplayControl.ProcessBar.Visible = false;

            if(!string.IsNullOrEmpty(queryKeyword)) this.dataDisplayControl.Search(queryKeyword);

            if(!string.IsNullOrEmpty(this._fixedFirstRowColumnName))
            {
                this.dataDisplayControl.ShowTopSearhTextBox = false;
                this.dataDisplayControl.FixedFirstRowText(this._fixedFirstRowColumnName);
            }
        }


        #endregion

        #endregion


        private void OraclePackageForm_Disposed(object sender,EventArgs e)
        {
            try
            {
                this.backgroundWorkerPackage.CancelAsync();
                this.backgroundWorkerPackage_Body.CancelAsync();

                this.backgroundWorkerPackage.Dispose();
                this.backgroundWorkerPackage_Body.Dispose();
            }
            catch(Exception ex)
            {
                LogHelper.WriteErrLog(ex);
            }
        }
    }
}
